<template>
  <div class="app-container">
    <el-card style="height: calc(100vh - 250px); overflow-y: scroll">
      <!--工具栏-->
      <div class="head-container">
        <!-- 搜索 -->
        <el-input v-model="query.name" clearable size="small" placeholder="输入名称或编码搜索" style="width: 200px" class="filter-item" @keyup.enter.native="reloadPage" />

        <span>
          <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="reloadPage">搜索</el-button>
          <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetReloadPage">重置</el-button>
        </span>

        <div class="crud-opts">
          <span class="crud-opts-left">
            <el-button v-permission="permission.add" class="filter-item" size="mini" type="primary" icon="el-icon-plus" @click="toAdd">
              新增
            </el-button>
            <el-button v-permission="permission.edit" class="filter-item" size="mini" type="success" icon="el-icon-edit" :disabled="selections.length !== 1" @click="toEdit(selections[0])">
              修改
            </el-button>
            <el-button slot="reference" v-permission="permission.del" class="filter-item" type="danger" icon="el-icon-delete" size="mini" :disabled="selections.length === 0" @click="toDeleteMy(selections)">
              删除
            </el-button>
          </span>
        </div>
      </div>
      <!--表单渲染-->
      <el-dialog append-to-body :close-on-click-modal="false" :visible.sync="addShow" :title="myTitle" width="600px">
        <el-form ref="form" :inline="true" :model="myForm" :rules="rules" size="small" label-width="80px">
          <el-form-item label="菜单类型" prop="type">
            <el-radio-group v-model="myForm.type" size="mini" style="width: 288px">
              <el-radio-button label="0">导航栏或根目录</el-radio-button>
              <el-radio-button label="1">菜单</el-radio-button>
              <el-radio-button label="2">按钮</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-show="myForm.type !== '2'" label="菜单图标" prop="icon">
            <el-popover class="" placement="bottom-start" width="450" trigger="click" @show="$refs['iconSelect'].reset()">
              <IconSelect ref="iconSelect" @selected="selected" />
              <el-input slot="reference" v-model="myForm.icon" style="width: 450px" placeholder="点击选择图标" readonly>
                <svg-icon v-if="myForm.icon" slot="prefix" :icon-class="myForm.icon" class="el-input__icon" />
                <i v-else slot="prefix" class="el-icon-search el-input__icon" />
              </el-input>
            </el-popover>
            <i v-show="myForm.icon" class="el-icon-circle-close" @click="myForm.icon=''"></i>
          </el-form-item>
          <el-form-item v-show="myForm.type === '1'" label="默认选择" prop="iframe">
            <el-radio-group v-model="myForm.iframe" size="mini">
              <el-radio-button :label="true">是</el-radio-button>
              <el-radio-button :label="false">否</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-show="myForm.type === '1'" label="菜单缓存" prop="cache">
            <el-radio-group v-model="myForm.cache" size="mini">
              <el-radio-button label="true">是</el-radio-button>
              <el-radio-button label="false">否</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-show="myForm.type !== '2'" label="菜单可见" prop="hidden">
            <el-radio-group v-model="myForm.hidden" size="mini">
              <el-radio-button label="false">是</el-radio-button>
              <el-radio-button label="true">否</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-if="myForm.type === '1'" label-width="100px" label="crud按钮生成">
            <el-radio-group v-model="myForm.needGenBtns" size="mini">
              <el-radio-button :label="1">是</el-radio-button>
              <el-radio-button :label="2">否</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item v-if="myForm.type !== '2'" label="菜单名称" prop="name">
            <el-input v-model="myForm.name" placeholder="菜单名称" style="width: 178px" />
          </el-form-item>
          <el-form-item v-if="myForm.type !== '2'" prop="path" label="路由节点">
            <el-input v-model="myForm.path" style="width: 178px" />
          </el-form-item>
          <el-form-item label="按钮编码" v-if="myForm.type === '2'" prop="code">
            <el-input v-model="myForm.code" placeholder="按钮编码" style="width: 178px" />
          </el-form-item>
          <el-form-item label="菜单排序" prop="num">
            <el-input-number v-model.number="myForm.num" :min="0" :max="999" controls-position="right" style="width: 178px" />
          </el-form-item>
          <el-form-item v-show="myForm.type === '1'" label="组件路径" prop="component">
            <el-input v-model="myForm.component" style="width: 450px" placeholder="从项目views下一级目录开始" />
          </el-form-item>
          <el-form-item label="上级菜单" :prop="myForm.type !== '0' ? 'pcode' : ''">
            <treeselect v-model="myForm.pcode" :options="menus" :normalizer="normalizer" style="width: 450px" placeholder="选择上级" :zIndex="9999" />
          </el-form-item>
          <el-form-item v-if="myForm.pcode && myForm.pcode !== '0' && myForm.type === '0'" label="组件路径" prop="component">
            <el-input v-model="myForm.component" style="width: 450px" placeholder="从项目views下一级目录开始" />
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" plain @click="addShow = false">取消</el-button>

          <el-button :loading="submitStatus" type="primary" @click="goSubmit">确认</el-button>
        </div>
      </el-dialog>
      <!--表格渲染-->
      <el-table ref="table" v-loading="loading" lazy highlight-current-row :load="getMenus" :data="tableData" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" row-key="id" @select="selectOne" @select-all="selectAll">
        <el-table-column type="selection" width="55" />
        <el-table-column :show-overflow-tooltip="true" label="菜单名称" width="145px" prop="name" />
        <el-table-column prop="icon" label="图标" align="center" width="60px">
          <template slot-scope="scope">
            <svg-icon :icon-class="scope.row.icon ? scope.row.icon : ''" />
          </template>
        </el-table-column>
        <el-table-column prop="num" align="center" label="排序" width="200px" />
        <el-table-column :show-overflow-tooltip="true" prop="code" label="编码" width="200px" />
        <el-table-column :show-overflow-tooltip="true" prop="path" label="路径" />
        <el-table-column prop="hidden" label="可见" width="85px">
          <template slot-scope="scope">
            <span v-if="scope.row.hidden">否</span>
            <span v-else>是</span>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建日期" width="180px">
          <template slot-scope="scope">
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{{
              parseTime(scope.row.createTime)
            }}</span>
          </template>
        </el-table-column>
        <el-table-column v-permission="['admin', 'menu:edit', 'menu:del']" label="操作" width="130px" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button v-permission="permission.edit" size="mini" type="primary" icon="el-icon-edit" @click="toEdit(scope.row)" />

            <el-button v-permission="permission.del" slot="reference" type="danger" icon="el-icon-delete" size="mini" @click="toDeleteMy(scope.row)" />
          </template>
        </el-table-column>
      </el-table>
      <!--分页组件-->
      <el-pagination :page-size="page.size" :total="page.total" :current-page="page.page" style="margin-top: 8px" layout="total, prev, pager, next, sizes" @size-change="sizeChangeHandler($event)" @current-change="pageChangeHandler" />
    </el-card>
  </div>
</template>

<script>
import crudMenu from "@/api/system/menu";
import IconSelect from "@/components/IconSelect";
import { parseTime } from '@/utils/index'
export default {
  name: "Menu",
  components: {
    IconSelect
  },

  data() {
    return {
      loading: true,
      myTitle: "",
      maps: new Map(),
      myForm: {
        needGenBtns: "2",
        id: null,
        pcode: 0,
        name: null,
        code: null,
        icon: null,
        iframe: false,
        path: null,
        num: 999,
        hidden: false,
        remark: null,
        component: null,
        cache: false,
        type: "0",
      },
      selections: [], //选中的数据
      addShow: false, //用来弹窗显示
      page: {
        size: 10,
        total: 0,
        page: 1,
      },
      query: { pcode: 0, name: "" },
      submitStatus: false,
      tableData: [],

      menus: [],
      permission: {
        add: ["admin", "menu:add"],
        edit: ["admin", "menu:edit"],
        del: ["admin", "menu:del"],
      },
      rules: {
        name: [{ required: true, message: "请输入名称", trigger: "blur" }],
        code: [{ required: true, message: "请输入编码", trigger: "blur" }],
        path: [{ required: true, trigger: "blur", message: "请输入路由节点" }],
        pcode: [{ required: true, trigger: "blur", message: "请选择上级菜单" }],
      },
    };
  },
  mounted() {
    this.loadMenus();
    this.getData();
  },
  methods: {
    // 刷新页面时重置父节点下的子节点数据
    resetTreeNode(data) {
      const { pcode } = data
      if (pcode != '0') {
        const { tree, treeNode, resolve } = this.maps.get(pcode)
        this.$set(this.$refs.table.store.states.lazyTreeNodeMap, pcode, [])
        this.getMenus(tree, treeNode, resolve);
      }
    },
    parseTime,
    // 当前页改变
    pageChangeHandler(e) {
      this.page.page = e;
      this.getData();
    },
    // 每页条数改变
    sizeChangeHandler(e) {
      this.page.size = e;
      this.page.page = 1;
      this.getData();
    },
    //点击删除
    toDeleteMy(data) {
      this.$confirm("确认要删除吗？")
        .then((_) => {
          let ids = [];
          if (data instanceof Array) {
            data.forEach((val) => {
              ids.push(val.id);
            });
          } else {
            ids.push(data.id);
          }
          crudMenu
            .del(ids)
            .then((res) => {
              if (res.code == 200) {
                this.$notify({
                  title: "成功",
                  message: "删除成功",
                  type: "success",
                });
                // 重置参数的子节点
                this.resetTreeNode(data)
                this.reloadPage();
              } else {
                this.$notify.error({
                  title: "错误",
                  message: "删除失败",
                });
              }
            })
        })
        .catch((_) => { });
    },
    //点击全选触发的方法
    selectAll(e) {
      this.selections = e;
    },
    selectOne(s, r) {
      this.selections = s;
    },
    //显示弹窗
    toAdd() {
      this.addShow = true;
      this.myTitle = "新增菜单";
      this.myForm = {
        needGenBtns: "2",
        id: null,
        pcode: 0,
        name: null,
        code: null,
        icon: null,
        iframe: false,
        path: null,
        num: 999,
        hidden: false,
        remark: null,
        component: null,
        cache: false,
        type: "0",
      };
      this.$nextTick(() => {
        this.$refs["form"].clearValidate();
      });
    },

    //显示弹窗赋值
    toEdit(data) {
      this.myForm = data;
      this.myTitle = "编辑菜单";
      this.addShow = true;
      this.$nextTick(() => {
        this.$refs["form"].clearValidate();
      });
    },

    // 提交前做的操作
    goSubmit() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          this.doSubmit();
        } else {
          console.log("error submit!!");
          return false;
        }
      });


    },

    //真正的去提交
    doSubmit() {
      this.submitStatus = true;
      crudMenu
        .edit(this.myForm)
        .then((res) => {
          this.submitStatus = false;
          if (res.code == 200) {
            this.$notify.success({
              title: "成功",
              message: "新增成功",
            });
            this.addShow = false;
            // 重置参数子节点
            this.resetTreeNode(this.myForm)
            //刷新表格
            this.reloadPage();
            this.loadMenus();
          }
        })
        .catch(() => {
          this.submitStatus = false;
        });
    },
    //重置搜索
    resetReloadPage() {
      this.page = {
        size: 10,
        total: 0,
        page: 1,
      };
      this.query = { pcode: 0 };
      this.getData();
    },
    //刷新第一页数据
    reloadPage() {
      this.page.page = 1;
      this.selections = [];
      this.getData();
    },
    getData() {
      if (this.query.name) {
        this.query.pcode = null;
      } else {
        this.query.pcode = "0";
      }

      this.query.pageNo = this.page.page - 1;
      this.query.pageSize = this.page.size;
      this.loading = true;
      crudMenu.list(this.query).then((res) => {
        if (res.code == 200) {
          this.loading = false;
          this.tableData = res.data.content;
          this.page.total = res.data.totalElements;

          res.data.content.forEach((o) => {
            if (o.type != "2") {
              o.hasChildren = true;
            }
          });
        }
      });
    },
    normalizer(node) {
      if (!node.data) {
        node.data = {
          code: "0",
          name: "请选择菜单",
        };
      }
      if (node.children == null || !node.children.length) {
        delete node.children;
      }
      return {
        id: node.data.code,
        label: node.data.name,
        children: node.children,
      };
    },
    getMenus(tree, treeNode, resolve) {
      // 保存tree父节点信息，建立映射
      const code = tree.code;
      this.maps.set(code, { tree, treeNode, resolve })
      // 获取所有下级
      const params = {
        pcode: code,
        pageNo: 0,
        pageSize: 999,
      };
      crudMenu
        .getMenus(params)
        .then((res) => {
          res.data.content.forEach((o) => {
            if (!o.isLeaf) {
              o.hasChildren = true;
            }
          });
          resolve(res.data.content);
        })
        .catch((err) => {
          console.log(err);
        });
    },
    loadMenus() {
      // 分页获取第一级
      const param = { type: 0 };
      crudMenu.getMenusTree(param).then((res) => {
        this.menus = res.data;
      });
    },
    // 选中图标
    selected(name) {
      this.myForm.icon = name;
    },
  },
};
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-input-number .el-input__inner {
  text-align: left;
}

::v-deep .vue-treeselect__control,
::v-deep .vue-treeselect__placeholder,
::v-deep .vue-treeselect__single-value {
  height: 30px;
  line-height: 30px;
}
::v-deep .el-input__icon {
  padding-top: 3px;
  height: 40px;
  width: 20px;
}
.el-icon-circle-close {
  margin-top: 5px;
  font-size: 26px;
  cursor: pointer;
}
</style>
<style>
.crud-opts {
  padding: 4px 0;
  display: -webkit-flex;
  display: flex;
  align-items: center;
}

.crud-opts .crud-opts-right {
  margin-left: auto;
}
</style>
